﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Web;
using Framework.Library.Core.Config;
using Framework.Library.Core.Data.DataManager;
using Framework.Library.Core.Data.DataProvider;
using Framework.Library.Core.Utils;
using Framework.Library.Core.Provider.Caches;
using Framework.Library.Core.Utils.GlobalHelper;
using Framework.Library.Core.Provider.Log;
using Framework.Library.Core.Utils.Database;

namespace Framework.Library.Core.Data.DataEngine
{
    public class GeneralConnection
    {
        private static Configurations cfg = new Configurations();
        
        public static int ExecuteNonQuery(CommandType connectionType, QueryBuilder builder)
        {
            int retVal = 0;
            string commandText = builder.Query;
            var qc = new GenerateCounter(commandText);
            Logger.Info(commandText);
            try
            {
                retVal = Configurations.DBMANAGER.ExecuteNonQuery(connectionType, commandText, builder.Parameters, false);
                if (retVal > 0)
                {
                    if (Configurations.Cache)
                        Caching.Data.InvalidateRegion(builder.Table);
                }
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
            }
            finally
            {
                qc.Reset();
            }
            return retVal;
        }

        public static object ExecuteScalar(CommandType connectionType, QueryBuilder builder)
        {
            object retVal = null;
            string commandText = builder.Query;
            var qc = new GenerateCounter(commandText);
            Logger.Info(commandText);         
            try
            {
                retVal = Configurations.DBMANAGER.ExecuteScalar(connectionType, commandText, builder.Parameters, false);
                
            }
            catch (Exception ex)
            {
                Logger.Error(ex);
            }
            finally
            {
                qc.Reset();
            }
            return retVal;
        }

        public static DataTable ExecuteDataTable(CommandType connectionType, QueryBuilder builder)
        {
            DataSet retVal = null;
            var cfg = new Configurations();
            string commandText = builder.Query;

            if (!Configurations.Cache)
            {
                retVal = Configurations.DBMANAGER.ExecuteDataSet(connectionType, commandText, builder.Parameters, false);
                if (retVal != null)
                {
                    if (retVal.Tables.Count > 0)
                    {
                        if (retVal.Tables[0].Rows.Count > 0)
                            return retVal.Tables[0];
                    }
                }
            }
            else
            {
                string param = string.Empty;
                if (builder.Parameters != null)
                {
                    for (int i = 0; i < (builder.Parameters.Count); i++)
                    {
                        var arr = (object[])builder.Parameters[i];
                        if (i == 0)
                            param += arr[0] + "=" + arr[1].GetHashCode();
                        else
                            param += "&" + arr[0] + "=" + arr[1].GetHashCode();
                    }
                }
                var dt = Caching.Data.Get<DataTable>(builder.Table, (commandText + "?" + param).GetHashCode().ToString());
                if (dt != null) return dt;
                var qc = new GenerateCounter(commandText);
                Logger.Info(commandText);
                try
                {
                    retVal = Configurations.DBMANAGER.ExecuteDataSet(connectionType, commandText, builder.Parameters, false);
                    if (retVal != null)
                    {
                        if (retVal.Tables.Count > 0)
                        {
                            if (retVal.Tables[0].Rows.Count > 0)
                            {
                                dt = retVal.Tables[0];
                                Caching.Data.Set(builder.Table, dt, (commandText + "?" + param).GetHashCode().ToString());
                                return dt;
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.Error(ex);
                }
                finally
                {
                    qc.Reset();
                }
            }

            return null;
        }

        public static List<T> ExecuteList<T>(CommandType connectionType, QueryBuilder builder)
        {
            var retVal = new List<T>();
            string commandText = builder.Query;

            if (!Configurations.Cache)
                retVal = Configurations.DBMANAGER.ExecuteList<T>(connectionType, commandText, builder.Parameters, false);
            else
            {
                string param = string.Empty;
                if (builder.Parameters != null)
                {
                    for (int i = 0; i < (builder.Parameters.Count); i++)
                    {
                        var arr = (object[])builder.Parameters[i];
                        if (i == 0)
                            param += arr[0] + "=" + arr[1].GetHashCode();
                        else
                            param += "&" + arr[0] + "=" + arr[1].GetHashCode();
                    }
                }
                retVal = Caching.Data.Get<List<T>>(builder.Table, (commandText + "?" + param).GetHashCode().ToString());
                if (retVal == null)
                {
                    var qc = new GenerateCounter(commandText);
                    Logger.Info(commandText);
                    try
                    {
                        retVal = Configurations.DBMANAGER.ExecuteList<T>(connectionType, commandText, builder.Parameters, false);
                        if (retVal != null)
                            Caching.Data.Set(builder.Table, retVal, (commandText + "?" + param).GetHashCode().ToString());
                    }
                    catch (Exception ex)
                    {
                        Logger.Error(ex);
                    }
                    finally
                    {
                        qc.Reset();
                    }
                }
            }
            if (retVal != null)
                return retVal;
            return new List<T>();
        }

        public static List<T> ExecuteList<T>(CommandType connectionType, QueryBuilder builder, out int Total)
        {
            var retVal = new List<T>();
            Total = 0;
            string commandText = builder.Query;
            if (!Configurations.Cache)
                retVal = Configurations.DBMANAGER.ExecuteList<T>(connectionType, commandText, builder.Parameters, false, out Total);
            else
            {
                string param = string.Empty;
                if (builder.Parameters != null)
                {
                    for (int i = 0; i < (builder.Parameters.Count); i++)
                    {
                        var arr = (object[])builder.Parameters[i];
                        if (i == 0)
                            param += arr[0] + "=" + arr[1].GetHashCode();
                        else
                            param += "&" + arr[0] + "=" + arr[1].GetHashCode();
                    }
                }
                retVal = Caching.Data.Get<List<T>>(builder.Table, (commandText + "?" + param).GetHashCode().ToString());
                if (retVal == null)
                {
                    var qc = new GenerateCounter(commandText);
                    Logger.Info(commandText);
                    try
                    {
                        retVal = Configurations.DBMANAGER.ExecuteList<T>(connectionType, commandText, builder.Parameters, false, out Total);
                        if (retVal != null)
                            Caching.Data.Set(builder.Table, retVal, (commandText + "?" + param).GetHashCode().ToString());
                    }
                    catch (Exception ex)
                    {
                        Logger.Error(ex);
                    }
                    finally
                    {
                        qc.Reset();
                    }
                }
                if (retVal != null)
                    return retVal;
            }
            return new List<T>();
        }
    }
}